{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Floating point and finite number representation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What will the following code snippet do?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from time import sleep\n",
    "\n",
    "x = 0.0\n",
    "\n",
    "while x != 1.0:\n",
    "    x += 0.1\n",
    "    print(repr(x))\n",
    "    \n",
    "    sleep(0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "How do you prevent that from happening?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Complexity: Timing Matrix Matrix Multiplication"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from time import process_time\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 2000\n",
    "A = np.random.randn(n,n)\n",
    "B = np.random.randn(n,n)\n",
    "\n",
    "t = process_time()  # store the time\n",
    "C = A @ B\n",
    "t = process_time() - t\n",
    "print(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 2000\n",
    "a = 2\n",
    "A = np.random.randn(a*n,a*n)\n",
    "B = np.random.randn(a*n,a*n)\n",
    "\n",
    "t2 = process_time()  # store the time\n",
    "C = A @ B\n",
    "t2 = process_time() - t2\n",
    "print(t2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "t2/t"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Plotting time versus matrix dimension"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as pt\n",
    "%matplotlib inline\n",
    "from time import process_time\n",
    "\n",
    "def get_solve_time(n):\n",
    "    A = np.random.randn(n, n)\n",
    "    B = np.random.randn(n, n)\n",
    "    \n",
    "    t_start = process_time()\n",
    "    A @ B\n",
    "    t_stop = process_time()\n",
    "    \n",
    "    return t_stop-t_start"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_values = np.array([100,1000,2000,3000,4000,5000,6000,8000,10000])\n",
    "print(n_values)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "times = []\n",
    "for n in n_values:\n",
    "    newtime = get_solve_time(n)\n",
    "    times.append(newtime)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pt.loglog(n_values, times)\n",
    "pt.xlabel('n')\n",
    "pt.ylabel('time')\n",
    "pt.grid()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Can we predict individual values?\n",
    "* What does the overall behavior look like?\n",
    "* How could we determine the \"underlying\" function?"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
